package com.anyi.listener;

import com.anyi.entity.Article;
import com.anyi.service.ArticleService;
import com.anyi.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Set;

/**
 * @author 安逸i
 * @version 1.0
 */

@Slf4j
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ListenHandler {
    @Autowired
    private ArticleService articleService;
    @Autowired
    private RedisUtil redisUtil;
    private static final String VIEW_KEY = "viewCounts";
    private static final String LIKE_KEY = "likeCounts";


    @PostConstruct
    public void init() throws Exception {
        log.info("数据初始化开始...");
        //将数据库中的数据写入redis
        List<Article> articleLst = articleService.list();
        articleLst.forEach(article -> {
            //将浏览量、点赞数和评论数写入redis
            redisUtil.zAdd(VIEW_KEY, article.getId().toString(), article.getViewCounts());
            redisUtil.zAdd(LIKE_KEY, article.getId().toString(), article.getLikeCounts());
        });
        log.info("数据已写入redis...");
    }

    /**
     * 关闭时操作
     */
    @PreDestroy
    public void afterDestroy() {
        log.info("开始关闭...");
        Set<ZSetOperations.TypedTuple<String>> viewCounts = redisUtil.zReverseRangeWithScores("viewCounts", 0, 10);
        Set<ZSetOperations.TypedTuple<String>> likeCounts = redisUtil.zReverseRangeWithScores("likeCounts", 0, 10);
        writeNum(viewCounts, VIEW_KEY);
        writeNum(likeCounts, LIKE_KEY);
        log.info("redis写入数据库完毕");
    }

    @Scheduled(cron = "*/15 * * * * ?")
    public void updateNum() {
        log.info("周期任务开始执行...");
        Set<ZSetOperations.TypedTuple<String>> viewCounts = redisUtil.zReverseRangeWithScores("viewCounts", 0, 10);
        Set<ZSetOperations.TypedTuple<String>> likeCounts = redisUtil.zReverseRangeWithScores("likeCounts", 0, 10);
        writeNum(viewCounts, VIEW_KEY);
        writeNum(likeCounts, LIKE_KEY);
        log.info("周期任务执行完毕,redis写入数据库完毕");
    }

    private void writeNum(Set<ZSetOperations.TypedTuple<String>> set, String fieldName) {
        set.forEach(item -> {
            Long id = Long.valueOf(item.getValue());
            Integer num = item.getScore().intValue();
            Article article = articleService.getById(id);
            if(article != null){
                if(fieldName.equals(VIEW_KEY)){
                    article.setViewCounts(num);
                }else if(fieldName.equals(LIKE_KEY)){
                    article.setLikeCounts(num);
                } else {
                    return;
                }

                //更新数据库
                articleService.updateById(article);
            }
        });
    }
}
